Overcome 4MB mail limit sent from Microsoft Flow
Table of contents:
On 21st August 2019 Microsoft announced that actions in Microsoft Flow from Outlook stack, are going to be moved from using Outlook REST API v1.0 to Microsoft Graph v1.0. Along with that information there was also written, that current Outlook API 1.0 is going to be decommissioned in 1st of November 2019. So after that date all old actions in Microsoft Flow are going to be removed too.
There would be nothing wrong with this transition, moreover – it is motivated by important arguments, however together with positive aspects it has one, significant negative issue: total size of the message sent to Microsoft Graph v1.0 API and the size of each attachment cannot exceed 4MB. That means – large attachments simply cannot be sent from Flow anymore.
The story behind
When browsing the internet looking for any sort of workaround or information about when the problem is going to be solved, I found these two assets:
- UserVoice entry: https://powerusers.microsoft.com/t5/Flow-Ideas/Send-Email-with-Option-File-Size-Limit/idi-p/337826 – confirming this issue is a struggle for many users…
- Github discussion: https://github.com/microsoftgraph/microsoft-graph-docs/issues/4370#issuecomment-536143650
The github one made me somehow more happy, as I read there, that Microsoft is like weeks away from releasing the beta update, allowing to send messages with attachments bigger, but without a precise information how big. But “weeks” can mean 2 or 10. And the requirement from one of my customers was very clear and urgent – we need to be able to send attachments bigger than 4MB using Flow.
The workaround aka solution
The solution to overcome 4MB attachments sent from Microsoft Flow that was mentioned mostly often (user Alhric Lacle shared parts of CSOM code) was the one encouraging to use Outlook REST API v2.0 that is not going to be decommissioned (or at least at the time of writing this post there was no information about that).
At first idea was quite simple to me:
- Create Azure AD app
- Grant it application permissions for Mail.ReadWrite and Mail.Send scopes
- Grant administrator consent
- Use one HTTP request action to call authentication endpoint to get Bearer token
- Use the token to send e-mail with attachments using defined in documentation methods: https://docs.microsoft.com/en-us/previous-versions/office/office-365-api/api/version-2.0/mail-rest-operations.
During test with Postman I realized, that this is impossible however. Even though I was able to obtain bearer token, I wasn’t able to call endpont to send mail, as I was constantly receiving access denied.
The reason why I think it was happening was due to the fact, the app was registered in a context of the application, not a user, but the API was expecting context of a user. But that’s just a guess.
Nevertheless, after failing several times more I asked Twitter for help:
And the help came from Vivek Bavishi (thank you pal!). He suggested to use built-in action in Microsoft Flow, called “Invoke an HTTP request” from the “HTTP with Azure AD“.
Important! These action are premium. You need to have Flow per flow license or per user to use them.
I decided to give it a try. The biggest difference between using the built-in actions and the HTTP requests is that in the OOTB approach there is really no need to first call authentication endpoint to obtain bearer token.
Important! All names in JSON schema are camelCased. Therefore be sure to really copy them 1-1 from the documentation examples.
I decided to use endpoint called https://outlook.office.com/api/v2.0/users/{USER-EMAIL}/sendmail to send a message on behalf of a shared mailbox.
Important! When creating a connection be sure you are using credentials of a user who has permissions to send on behalf of other user/ mailbox. That’s the key point in this approach.
I also wanted my message to be sent to multiple recipients. There are two arrays:
"ToRecipients": [ ], "CcRecipients": [ ],
In each you need to put every recipient’s e-mail in a separate block:
{ "EmailAddress": { "Address": "SINGLE EMAIL ADDRESS" } }
Therefore you cannot simply put a string with multiple, semicolon separated e-mails.
I prepared those blocks, by first splitting and then immidiately joining a list of semicolon separated e-mail adressess, by using the below expression:
split(body('mail1@test.com;mail2@test.com', ';')
For this purpose I used action called “Join”. The “Join with” string was:
"}},{"EmailAddress": { "Address": "
So that they perfectly fit then inside the block:
{ "EmailAddress": { "Address": "OUTCOME OF THE JOIN ACTION" } }
Next step is to attach documents. Here the crucial think to remember is that the contents of the file must be base64 encoded. Files are stored in an array named “Attachments”:
"Attachments": [ ]
Each attachment is an object, built using the following schema:
{ "@odata.type": "#Microsoft.OutlookServices.FileAttachment", "Name": "FILENAME", "ContentBytes": "BASE64 ENCODED FILE CONTENTS" }
There are also additional options in the schema, such as “SaveToSentItems”, however the main core of the action are recipients, contents of the mail and attachments. The final action just to send the mail on the fly looks like:
The biggest file I tried to send was 18MB, however it should be possible to send files up to 50MB as well.
I hope you find this post helpful. And that it will save you a lot of time searching how to overcome limit. I also personally hope that it information written here will very soon get useles because of the increase in limit present in Graph API v1.0 😉
Stay tuned!